﻿/************************************************************************

   Extended Silverlight Toolkit

   Copyright (C) 2010-2012 Xceed Software Inc.

   This program is provided to you under the terms of the Microsoft Public
   License (Ms-PL) as published at http://extendedsilverlight.codeplex.com/license

   Please purchase a commercial version of this toolkit if you are using
   it in a commercial product. The commercial versions support the project,
   and also include more features for each control, priority support,
   source code, updates, removed watermark, and a proprietary license.

   Visit http://xceed.com and follow @datagrid on Twitter.

  **********************************************************************/

using System.Collections.Generic;
using System.Linq;

namespace Xceed.Silverlight.DataGrid
{
  internal class MergeInfo
  {
    internal bool ScrollForward
    {
      get
      {
        return m_scrollForward;
      }
    }

    internal IList<ILayoutElement> OldLayoutItems
    {
      get
      {
        return m_oldLayout;
      }
    }

    internal IList<ILayoutElement> NewLayoutItems
    {
      get
      {
        return m_newLayout;
      }
    }

    internal IEnumerable<ILayoutElement> RemovedItems
    {
      get
      {
        return m_removedElements;
      }
    }

    internal IEnumerable<ILayoutElement> AddedItems
    {
      get
      {
        return m_addedElements;
      }
    }

    internal IList<ILayoutElement> ScrolledOutItems
    {
      get
      {
        return m_scrolledOutItems;
      }
    }

    internal IList<ILayoutElement> ScrolledInItems
    {
      get
      {
        return m_scrolledInItems;
      }
    }

    internal IEnumerable<ILayoutElement> AllItems
    {
      get
      {
        return m_allElements;
      }
    }

    internal IEnumerable<ILayoutElement> ScrollingItems
    {
      get
      {
        return m_scrollingItems;
      }
    }

    public MergeInfo(
      IEnumerable<ILayoutElement> oldElements,
      IEnumerable<ILayoutElement> newElements,
      bool scrollForward )
    {
      m_scrollForward = scrollForward;
      m_newLayout = newElements.ToList();
      m_oldLayout = oldElements.ToList();

      m_oldItemsHash = new HashSet<ILayoutElement>( m_oldLayout );
      m_newItemsHash = new HashSet<ILayoutElement>( m_newLayout );
      m_allElements = new HashSet<ILayoutElement>( m_oldItemsHash.Union( m_newItemsHash ) );

      if( !scrollForward )
      {
        m_newLayout.Reverse();
        m_oldLayout.Reverse();
      }

      bool scrolledOut = true;
      m_scrolledOutItems = new List<ILayoutElement>();
      m_removedElements = new HashSet<ILayoutElement>();
      m_scrollingItems = new List<ILayoutElement>();
      foreach( ILayoutElement element in m_oldLayout )
      {
        if( !m_newItemsHash.Contains( element ) )
        {
          if( scrolledOut )
          {
            m_scrollingItems.Add( element );
            m_scrolledOutItems.Add( element );
          }
          else
          {
            m_removedElements.Add( element );
          }
        }
        else
        {
          scrolledOut = false;
        }
      }

      m_scrollingItems.AddRange( m_newLayout );

      bool scrolledIn = true;
      m_scrolledInItems = new List<ILayoutElement>();
      m_addedElements = new HashSet<ILayoutElement>();
      for( int i = m_newLayout.Count - 1; i >= 0; i-- )
      {
        ILayoutElement element = m_newLayout[ i ];
        if( !m_oldItemsHash.Contains( element ) )
        {
          if( scrolledIn )
          {
            m_scrolledInItems.Add( element );
          }
          else
          {
            m_addedElements.Add( element );
          }
        }
        else
        {
          scrolledIn = false;
        }
      }

      m_scrolledInItems.Reverse();


      if( !scrollForward )
      {
        m_scrolledInItems.Reverse();
        m_scrolledOutItems.Reverse();
        m_scrollingItems.Reverse();
        m_oldLayout.Reverse();
        m_newLayout.Reverse();
      }

    }

    private HashSet<ILayoutElement> m_allElements;
    private HashSet<ILayoutElement> m_oldItemsHash;
    private HashSet<ILayoutElement> m_newItemsHash;
    private HashSet<ILayoutElement> m_removedElements;
    private HashSet<ILayoutElement> m_addedElements;
    private List<ILayoutElement> m_scrolledOutItems;
    private List<ILayoutElement> m_scrolledInItems;
    private List<ILayoutElement> m_newLayout;
    private List<ILayoutElement> m_oldLayout;
    private List<ILayoutElement> m_scrollingItems;
    private bool m_scrollForward;
  }
}
